#include "tools/file.hpp"
#include "tools/api.hpp"
#include <string>
#include <utility>
#include <filesystem>
#include <fstream>
#include <map>

namespace toolsLib
{
File::File() {}

File::~File() {}

File& File::getInstance()
{
    static toolsLib::File instance;
    return instance;
}

bool File::extractSameNameFile(const std::string& directory1,
                               const std::string& directory2,
                               std::vector<std::string>& result)
{
    try {
        namespace fs = std::filesystem;
        
        fs::path dir1(directory1);
        fs::path dir2(directory2);
        
        // 检查目录是否存在
        if (!fs::exists(dir1) || !fs::is_directory(dir1)) {
            LOG_ERROR("Directory 1 does not exist or is not a directory: %s", directory1.c_str());
            return false;
        }
        
        if (!fs::exists(dir2) || !fs::is_directory(dir2)) {
            LOG_ERROR("Directory 2 does not exist or is not a directory: %s", directory2.c_str());
            return false;
        }
        
        // 获取两个目录中的文件名（不含扩展名）
        std::map<std::string, std::string> dir1Names;  // name -> full path
        std::map<std::string, std::string> dir2Names;  // name -> full path
        
        for (const auto& entry : fs::directory_iterator(dir1)) {
            if (fs::is_regular_file(entry)) {
                std::string name;
                GET_NAME(entry.path().string(), name);
                if (!name.empty()) {
                    dir1Names[name] = entry.path().string();
                }
            }
        }
        
        for (const auto& entry : fs::directory_iterator(dir2)) {
            if (fs::is_regular_file(entry)) {
                std::string name;
                GET_NAME(entry.path().string(), name);
                if (!name.empty()) {
                    dir2Names[name] = entry.path().string();
                }
            }
        }
        
        if (dir1Names.empty() || dir2Names.empty()) {
            LOG_ERROR("One or both directories are empty");
            return false;
        }
        
        result.clear();
        
        // 找出两个目录中同名的文件
        for (const auto& pair : dir1Names) {
            if (dir2Names.find(pair.first) != dir2Names.end()) {
                result.push_back(pair.first);
            }
        }
        
        return true;
    } catch (const std::filesystem::filesystem_error& e) {
        LOG_ERROR("Failed to extract same name files: %s", e.what());
        return false;
    } catch (...) {
        LOG_ERROR("Unknown error occurred while extracting same name files");
        return false;
    }
}

bool File::filtrateFileFromCSV(const std::string& csvFile,
                               const std::string sourceDir,
                               const std::string targetDir)
{
    try {
        namespace fs = std::filesystem;
        
        // 检查CSV文件是否存在
        if (!fs::exists(csvFile)) {
            LOG_ERROR("CSV file does not exist: %s", csvFile.c_str());
            return false;
        }
        
        // 检查源目录是否存在
        if (!fs::exists(sourceDir) || !fs::is_directory(sourceDir)) {
            LOG_ERROR("Source directory does not exist or is not a directory: %s", sourceDir.c_str());
            return false;
        }
        
        // 确保目标目录存在
        fs::path targetPath(targetDir);
        fs::create_directories(targetPath);
        
        std::ifstream fileStream(csvFile);
        if (!fileStream.is_open()) {
            LOG_ERROR("无法打开 CSV 文件: %s", csvFile.c_str());
            return false;
        }
        
        std::vector<std::string> selectedFiles;
        std::map<std::string, std::string> nameToPath;  // name -> full path
        
        // 获取源文件夹中所有文件，建立文件名到路径的映射
        for (const auto& entry : fs::directory_iterator(sourceDir)) {
            if (fs::is_regular_file(entry)) {
                std::string name;
                GET_NAME(entry.path().string(), name);
                if (!name.empty()) {
                    nameToPath[name] = entry.path().string();
                }
            }
        }
        
        // 遍历 CSV 中的文件名
        std::string line;
        while (std::getline(fileStream, line)) {
            // 跳过空行和只包含空白字符的行
            if (line.empty() || line.find_first_not_of(" \t\n\r") == std::string::npos) {
                continue;
            }
            
            // 去除文件名中的路径和后缀信息
            std::string csvName;
            GET_NAME(line, csvName);
            
            // 在源目录中查找匹配的文件
            for (const auto& pair : nameToPath) {
                if (pair.first.find(csvName) != std::string::npos || 
                    csvName.find(pair.first) != std::string::npos) {
                    selectedFiles.push_back(pair.second);
                    break;
                }
            }
        }
        
        fileStream.close();
        
        // 复制选中的文件到目标目录
        for (const auto& file : selectedFiles) {
            LOG_INFO(file);
            fs::path sourcePath(file);
            fs::path targetFilePath = targetPath / sourcePath.filename();
            
            // 复制文件
            fs::copy_file(sourcePath, targetFilePath, fs::copy_options::overwrite_existing);
        }
        
        return true;
    } catch (const std::filesystem::filesystem_error& e) {
        LOG_ERROR("Failed to filtrate files from CSV: %s", e.what());
        return false;
    } catch (const std::exception& e) {
        LOG_ERROR("Error occurred while filtrating files: %s", e.what());
        return false;
    } catch (...) {
        LOG_ERROR("Unknown error occurred while filtrating files");
        return false;
    }
}

}  // namespace toolsLib